const debug = require('debug')('apifaker:middleware');
const _ = require('lodash');
const { MGObject, MGQuery } = require('fpmc-jssdk');
const axios = require('axios');

// 处理路由的mock中间件
exports.mock = async (ctx, next) => {

    const { url, method = 'GET', header = {}, query = {}, body = {} } = ctx.request;

    if(_.startsWith(url, '/faker')){
        next();
        return;
    }
    
    const data = {
        request: {
            url,
            method,
            header,
            query,
            body,
        },
        startAt: _.now(),
    }
    const requestData = method === 'GET'? query: body;

    let response;

    let env = 'MOCK';

    let forwardUrl ;

    try {

        // 获取 请求映射 的处理类型
        const mgRsp = await new MGQuery('mockapi', 'mock_request_mapper')
                                                        .condition({
                                                            request_key: `${method}_${url}`
                                                        })
                                                        .first();
        const { data } = mgRsp;
        env = data.env;
        forwardUrl = data.forward;
        debug('获取mapper: %O', data)
    } catch (error) {
        // 未定义
        debug('未定义的路由 mapper: %s', `${method}_${url}`);
    }

    try {
        
        
        if(env === 'DEMO' || env === 'MOCK'){
            response = await readMockData(data.request, requestData)
        }else if(env === 'FORWARD') {
            response = await forwardRequest(data.request, requestData, forwardUrl);
        }
    } catch (error) {
        ctx.body = {
            errno: -1,
            error: error.message,
        }
        return;
    }

    try {
        data.response = response;
        data.endAt = _.now();
        data.cost = data.endAt - data.startAt;

        await new MGObject('mockapi', 'mock_request_record')
        .set(data)
        .create();
    } catch (error) {
        debug('记录请求返回信息失败', error);
    }

    ctx.body = response;
    
    // await next();
}

const forwardRequest = async ( request, requestData, forwardUrl )  => {
    const { 
        url,
        method,
        body,
        query,
        header,
    } = request;
    try {
        
        const rsp = await axios({
            method: _.toLower(method),
            url: forwardUrl + url,
            headers: header,
            params: query,
            data: body,
            timeout: 10000

        });

        const { status, data } = rsp;
        debug('转发请求结果 %d, %O', status, data);
        return data;
    } catch (error) {
        debug('转发请求错误: %O', error);
        return {
            errno: 9999,
            error: error.message,
        }
    }
    
}

const readMockData = async ( request, requestData )  => {
    const { 
        url,
        method,
    } = request;
    try {
        const request_key = `${method}_${url}`;
        const rsp = await new MGQuery('mockapi', 'mock_respone_dataset')
                                    .condition(_.assign({
                                        request_key,
                                    }, requestData ))
                                    .first();
        return rsp.data.response;        
    } catch (error) {
        if(!!error._error){
            if(error._error.errno === -3){
                return {};
            }
        }
        throw error;
    }
}